/*******************************************************************
 *
 * Copyright (C), 2021-2022, LS, All rights reserved.
 *
 * Author      : 
 * Create Time : 2020-11-02
 * Version     : v0.1
 * Description : 
 *******************************************************************/

/*----------------------------Head file----------------------------*/
#include "spi.h"
#include "dma.h"
#include "string.h"
#include "hal_display.h"
#include "bsp_hw_config.h"


/*----------------------------macro file---------------------------*/
#define HAL_DISP_LOG_EN         1

#if HAL_DISP_LOG_EN
#include "log.h"
#define HAL_DISP_LOG        	LOG
#else
#define HAL_DISP_LOG(...)
#endif


#define LCD_BL_OUTPUT_INIT()    hal_gpio_pin_init(BSP_DISP_BL_PIN_NUM, GPIO_OUTPUT)
#define LCD_BL_OUTPUT_LOW()     hal_gpio_write(BSP_DISP_BL_PIN_NUM, 0)
#define LCD_BL_OUTPUT_HIGH()    hal_gpio_write(BSP_DISP_BL_PIN_NUM, 1)

#define LCD_DC_OUTPUT_INIT()    hal_gpio_pin_init(BSP_DISP_DC_PIN_NUM, GPIO_OUTPUT)
#define LCD_DC_OUTPUT_LOW()     hal_gpio_write(BSP_DISP_DC_PIN_NUM, 0)
#define LCD_DC_OUTPUT_HIGH()    hal_gpio_write(BSP_DISP_DC_PIN_NUM, 1)

#define LCD_RST_OUTPUT_INIT()   hal_gpio_pin_init(BSP_DISP_RST_PIN_NUM, GPIO_OUTPUT)
#define LCD_RST_OUTPUT_LOW()    hal_gpio_write(BSP_DISP_RST_PIN_NUM, 0)
#define LCD_RST_OUTPUT_HIGH()   hal_gpio_write(BSP_DISP_RST_PIN_NUM, 1)

#define LCD_PWR_OUTPUT_INIT()   hal_gpio_pin_init(BSP_DISP_PWR_PIN_NUM, GPIO_OUTPUT)
#define LCD_PWR_CTRL_ENABLE()   hal_gpio_write(BSP_DISP_PWR_PIN_NUM, 0)
#define LCD_PWR_CTRL_DISABLE()  hal_gpio_write(BSP_DISP_PWR_PIN_NUM, 1)

/*----------------------------type define--------------------------*/

/*-------------------------func declarative------------------------*/
extern void disp_sem_tx_done(void);

/*----------------------------var define---------------------------*/
static bool backlight_state = false;
static bool lcd_spi_init_state = false;

static const hal_spi_t disp_spi =
{
    .spi_index = DISP_SPI_NUM,
};

/*-----------------------------------------------------------------*/

static void hal_disp_cb_evt(spi_evt_t *param)
{
    /*if(SPI_TX_COMPLETED == param->evt) {
        spi_busy = false;
    }*/
}


void hal_disp_send_block(const uint8_t *data, int len)
{
    if(false == lcd_spi_init_state || len <= 0)
        return;

    hal_spi_dma_set((hal_spi_t*)&disp_spi, 0, 0);
    hal_spi_set_int_mode((hal_spi_t*)&disp_spi, false);

    //hal_spi_TxComplete((hal_spi_t*)&disp_spi);    //no need for now
    int ret = hal_spi_transmit((hal_spi_t*)&disp_spi, SPI_TXD, (uint8_t*)data, NULL, len, 0);
    if(PPlus_SUCCESS != ret) {
        HAL_DISP_LOG("hal_disp_send_block failed: %d!.\n", ret);
        return;
    }
}

void hal_disp_send_noblock(const uint8_t *data, int len)
{
    if(false == lcd_spi_init_state || len <= 0)
        return;

    hal_spi_dma_set((hal_spi_t*)&disp_spi, 1, 0);
    hal_spi_set_int_mode((hal_spi_t*)&disp_spi, true);

    //hal_spi_TxComplete((hal_spi_t*)&disp_spi);    //no need for now
    hal_spi_set_tx_buffer((hal_spi_t*)&disp_spi, (uint8_t*)data, len);
    int ret = hal_spi_transmit((hal_spi_t*)&disp_spi, SPI_TXD, (uint8_t*)data, NULL, len, 0);
    if(PPlus_SUCCESS != ret) {
        HAL_DISP_LOG("hal_disp_send_noblock failed: %d!.\n", ret);
        return;
    }
}


void hal_disp_gpio_drv_init(void)
{
    LCD_PWR_OUTPUT_INIT();
    LCD_BL_OUTPUT_INIT();
    LCD_DC_OUTPUT_INIT();
    LCD_RST_OUTPUT_INIT();
    //GPIO need hal_gpioretention_register, or it will output low when MCU go to sleep.
    hal_gpioretention_register(BSP_DISP_PWR_PIN_NUM);
    
    LCD_PWR_CTRL_ENABLE();
    LCD_BL_OUTPUT_LOW();
    LCD_DC_OUTPUT_LOW();
    LCD_RST_OUTPUT_HIGH();
    WaitMs(150);
}

void hal_disp_gpio_drv_deinit(void)
{
    LCD_PWR_CTRL_DISABLE();
    LCD_BL_OUTPUT_LOW();
    LCD_DC_OUTPUT_LOW();
    LCD_RST_OUTPUT_LOW();
}


void hal_disp_spi_drv_init(void)
{
    spi_Cfg_t spi_cfg =
    {
        .sclk_pin = BSP_DISP_CLK_PIN_NUM,
        .ssn_pin = BSP_DISP_CS_PIN_NUM,
        .MOSI = BSP_DISP_MOSI_PIN_NUM,
        .MISO = GPIO_DUMMY,

        .baudrate = DISP_SPI_SPEED_HZ,
        .spi_tmod = SPI_TXD,
        .spi_scmod = SPI_MODE3,
        .spi_dfsmod = SPI_1BYTE,

#if DMAC_USE
        .dma_tx_enable = true,
        .dma_rx_enable = false,
#endif

        .int_mode = false,
        .force_cs = true,
        .evt_handler = hal_disp_cb_evt,
    };
    
    uint8_t ret = hal_spi_bus_init((hal_spi_t*)&disp_spi, spi_cfg);
    if(PPlus_SUCCESS != ret) {
        HAL_DISP_LOG("disp spi initial failed: %d!.\n", ret);
        return;
    }
    
#if DMAC_USE
    hal_dma_init();
#endif
    lcd_spi_init_state = true;
}


void hal_disp_spi_drv_deinit(void)
{
    lcd_spi_init_state = false;
#if DMAC_USE
    hal_dma_stop_channel(DMA_CH_0); //SPI use DMA_CH_0
    hal_dma_deinit();
#endif
    hal_spi_bus_deinit((hal_spi_t*)&disp_spi);
}


void hal_disp_set_pwr_pin(bool enable)
{
    if(enable) {
        LCD_PWR_CTRL_ENABLE();
    }
    else {
        LCD_PWR_CTRL_DISABLE();
    }
}

void hal_disp_set_dc_pin(bool enable)
{
    if(enable) {
        LCD_DC_OUTPUT_HIGH();
    }
    else {
        LCD_DC_OUTPUT_LOW();
    }
}

void hal_disp_set_reset_pin(bool enable)
{
    if(enable) {
        LCD_RST_OUTPUT_LOW();
    }
    else {
        LCD_RST_OUTPUT_HIGH();
    }
}

void hal_disp_set_backlight_pin(bool enable)
{
    if(false == backlight_state && enable) {
        LCD_BL_OUTPUT_HIGH();
        backlight_state = true;
    }
    else if(true == backlight_state && false == enable) {
        LCD_BL_OUTPUT_LOW();
        backlight_state = false;
    }
}


bool hal_disp_backlight_state_get(void)
{
    return backlight_state;
}

